( function( $ ) {
	$.fn.extend( {
		errorEcho: function( options ){
			options = $.extend({
				errorClass: "error",
				errorElement: "label",
				fieldErrorPlacement: function( error, element ){
					error.appendTo(element.parent());
				},
				golbalErrorPlacement: function( errors ){
					showGolbalErrors(errors);
				}
			}, options || {} );
			
			var form = this;

			var errorsType = options.errorsData.errorsType;
			var errors = options.errorsData.errors;

			if(errorsType === "ONLY_FIELD_ERRORS"){//只有字段错误
				showFieldErrors( form, errors, options );
			}else if (errorsType === "ONLY_GOLBAL_ERRORS") {//只有全局错误
				options.golbalErrorPlacement( errors );
			}else{//两种错误都有
				//显示字段错误
				showFieldErrors( form, errors, options );
				
				//显示全局错误
				options.golbalErrorPlacement( errors );
			}
		}
	} );

	/**
	 * 显示全局错误
	 * @param errors 后台返回的错误列表
	 */
	var showGolbalErrors = function( errors ){
		var errorsWin = generateGolbalError( errors );
		errorsWin.show();
	}

	/**
	 * 生成用于显示全局错误的html
	 * @param errors 后台返回的错误列表
	 */
	var generateGolbalError = function( errors ){
		var errorsWin = $( "#errorsWin" );
		if( !errorsWin.length ) {
			errorsWin = $( "<div></div>" ).arrt( "id", winId ).addClass("errors-win");
			var title = $("<h3></h3>").addClass("title");
			var ul = $("<ul></ul>").addClass("error-list");
			errorsWin.append(title);
			errorsWin.append(ul);
		}

		var errorUl = errorsWin.find("ul.error-list").eq(0);
		errorUl.empty();
		for( var i = 0, len = errors.length; i < len; i++ ){
			var li = $("<li></li>").addClass("error-item").text(errors[i]);
			errorUl.append(li)
		}
		return errorsWin;
	}

	/**
	 * 显示字段错误
	 * @param form 当前提交的表单(jQuery)
	 * @param errors 后台返回的错误列表
	 * @param options 用户设置的选项或默认的选项
	 */
	var showFieldErrors = function(form, errors, options){
		var errorElement = options.errorElement;
		var errorClass = options.errorClass;
		
		//清除上一次的错误信息
		clearBeforeErrors(errorElement, errorClass);
		
		if(errors.length){//如果有错误
			for(var i = 0, len = errors.length; i < len; i++){
				var fieldName = errors[i].field;
				var errorMessage = errors[i].message;
				var element= getElement(form, fieldName);
				var name = idOrName(element[0]);
				
				var error = generateFieldError(errorClass, errorElement, name, errorMessage);
				
				options.fieldErrorPlacement(error, element);
			}
		}
	}
	
	var clearBeforeErrors = function(errorElement, errorClass){
		var beforeErrors = $(errorElement + "." + errorClass);
		beforeErrors.length && beforeErrors.remove();
	}

	/**
	 * 生成用于显示字段错误的HTML
	 * @param errorClass 标记错误消息的样式
	 * @param errorElement 标记错误的标签
	 * @param filedName 发生错误的字段名
	 * @param errorMessage 错误消息
	 */
	var generateFieldError = function(errorClass, errorElement, filedName, errorMessage){
		var errorLabel = $("<" + errorElement + "></" + errorElement + ">")
		.attr("id", filedName + "-error").addClass(errorClass).text(errorMessage);
		if(errorElement === "label"){
			errorLabel.attr("for", filedName);
		}
		return errorLabel;
	}

	/**
	 * 获取发生错误的表单元素
	 * @param form 当前提交的表单(jQuery)
	 * @param filedName 发生错误的字段名
	 */
	var getElement = function(form, fieldName){
		var element = form.find(" [name='" + fieldName + "']");
		return element;
	}

	/**
	 * 根据元素的类型,获取其 ID 或 name
	 * @param element 要判断的元素
	 */
	var idOrName = function( element ) {
		return checkable( element ) ? element.name : (element.id || element.name );
	}

	/**
	 * 检查是否是可选元素
	 * @param 被检查的元素
	 */
	var checkable = function( element ) {
		return ( /radio|checkbox/i ).test( element.type );
	}

})( jQuery );